package com.east.sng.controller;

import com.east.sng.entity.param.UserParam;
import com.east.sng.entity.result.EncryptedData;
import com.east.sng.entity.result.MenuTree;
import com.east.sng.entity.result.UserFind;
import com.east.sng.service.MenuService;
import com.east.sng.service.UserService;
import com.east.sng.utils.EncryptDataUtil;
import com.east.sng.utils.ValidationUtil;
import com.east.sng.utils.VerifyCode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author east
 * @date: 2020/12/27
 * @Description: index controller
 **/
@Validated
@Controller
public class IndexController {
    @Autowired
    private UserService userService;
    @Autowired
    private MenuService menuService;

    /**
     * 首页跳转
     * @return
     */
    @RequestMapping(value = {"/","/index","/main","/index.html","/main.html"},method = RequestMethod.GET)
    public String toIndex(HttpSession session) {
        //根据用户序列号查询授予的菜单
        UserFind u = (UserFind) SecurityUtils.getSubject().getPrincipal();
        if (u!=null) {
            List<MenuTree> menus = menuService.findMenuByRoleId(u.getRoleId());
            //定义变量临时存放所有菜单
            HashMap<Integer, MenuTree> menuTreeMaps = new HashMap();
            //将所有菜单存入，组织格式
            menus.forEach((item) -> {
                menuTreeMaps.put(item.getMenuId(), item);
            });
            //定义变量临时存放一级菜单
            List firstMenu = new ArrayList<String>();
            //组织一级菜单和子菜单
            menus.forEach((item) -> {
                if (item.getParentId() == 0) {
                    //保存一级菜单
                    firstMenu.add(item);
                } else {
                    //让其他级别的菜单连接上一级菜单
                    menuTreeMaps.get(item.getParentId()).getChildren().add(item);
                }
            });
            session.setAttribute("userMenu", firstMenu);
            return "index/main";
        } else {
            return "redirect:/login";
        }

    }

    /**
     * 登录页面跳转
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String toLogin(){
        return "login";
    }

    /**
     * 注册页面跳转
     * @return
     */
    @RequestMapping(value = "/register",method = RequestMethod.GET)
    public String toRegister(){
        return "register";
    }

    /**
     * 验证码显示
     * @param response
     * @param session
     */
    @RequestMapping("/captcha")
    @SuppressWarnings("static-access")
    public void captcha(HttpServletResponse response, HttpSession session) {
        //获取验证码对象
        VerifyCode vc = new VerifyCode();
        //获取图片
        BufferedImage img = vc.getImage();
        //获取文字
        String text = vc.getText();
        //保存文字到session
        session.setAttribute("code", text);
        //输出图片
        try {
            VerifyCode.output(img, response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 登录验证
     * @param user
     * @param captcha
     * @param session
     * @param model
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(UserParam user, String captcha, HttpSession session, Model model){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getUserPassword());
        try {
            //执行登录操作
            subject.login(token);
            String code = (String) session.getAttribute("code");
            if (code==null || !code.equalsIgnoreCase(captcha)) {
                model.addAttribute("msg","您输入的验证码不正确");
                return "login";
            }
        } catch (IncorrectCredentialsException e) { //密码输入错误
            model.addAttribute("msg","用户名或者密码输入有误");
            return "login";
        } catch (AuthenticationException e) { //用户名输入错误
            model.addAttribute("msg","用户名或者密码输入有误");
            return "login";
        }
        return "redirect:/index";
    }

    /**
     * 注册用户
     * @param user
     * @param captcha
     * @param session
     * @param model
     * @return
     */
    @RequestMapping(value = "/register",method = RequestMethod.POST)
    public String register(@Valid UserParam user, BindingResult br, @NotBlank(message = "{user.captcha.notblank}") String captcha, HttpSession session, Model model){
        ValidationUtil.validateData(br);
        if (this.userService.checkUserName(user.getUserName())){
            String code = (String) session.getAttribute("code");
            if (code!=null && code.equalsIgnoreCase(captcha)) {
                //进行盐值加密
                EncryptedData encryptedData = EncryptDataUtil.encryptPasswrod(user.getUserPassword());
                user.setUserPassword(encryptedData.getEncryptedPwd());
                user.setSalt(encryptedData.getSalt());
                userService.addUser(user);
                return "redirect:/login";
            }
            model.addAttribute("msg","您输入的验证码不正确");
        }else {
            model.addAttribute("msg","账号已被注册");
        }
        return "register";
    }

    /**
     * 退出登录
     * @return
     */
    @RequestMapping(value = "/logout",method = RequestMethod.GET)
    public String logout(){
        SecurityUtils.getSubject().logout();
        return "redirect:/login";
    }

}
